package com.xyz.apis.config;

import com.alibaba.druid.support.http.StatViewServlet;
import com.google.common.collect.Lists;
import com.google.common.util.concurrent.ThreadFactoryBuilder;
import com.netflix.hystrix.contrib.metrics.eventstream.HystrixMetricsStreamServlet;
import com.sc.base.common.spring.config.MybatisSQLPerConfiguration;
import com.sc.base.common.spring.config.RedisConfiguration;
import com.sc.base.common.spring.config.ShardingDataSourceConfiguration;
import com.sc.base.common.spring.feign.FeignCustomConfiguration;
import com.sc.base.common.spring.security.SpringSecurityBaseConfiguration;
import com.thetransactioncompany.cors.CORSFilter;
import com.xyz.apis.common.utils.SnowflakeIdWorker;
import org.mybatis.spring.annotation.MapperScan;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.cloud.openfeign.EnableFeignClients;
import org.springframework.cloud.openfeign.FeignClientsConfiguration;
import org.springframework.context.annotation.*;

import javax.servlet.DispatcherType;
import java.util.concurrent.*;

@Configuration
@MapperScan(basePackages = {"com.xyz.apis.**.mapper"})
@ComponentScan({"com.xyz.apis.**.service"})
@EnableFeignClients(basePackages={"com.xyz.apis.common.interfaces"},defaultConfiguration = FeignClientsConfiguration.class)
@Import({MybatisSQLPerConfiguration.class, ShardingDataSourceConfiguration.class, RedisConfiguration.class,
        SpringSecurityBaseConfiguration.class,Swagger2Config.class,HazelcastConfiguration.class, FeignCustomConfiguration.class})
public class XApisConfiguration {
    protected Logger logger = LoggerFactory.getLogger(getClass());


    @Bean
    public SnowflakeIdWorker snowflakeIdWorker(){
        return  new SnowflakeIdWorker(1, 0);
    }


    //@Bean
    public ServletRegistrationBean getServlet() {
        //http://192.168.1.117:8091/hystrix
        //http://192.168.1.117:8091/hystrix.stream
        HystrixMetricsStreamServlet streamServlet = new HystrixMetricsStreamServlet();
        ServletRegistrationBean registrationBean = new ServletRegistrationBean(streamServlet);
        registrationBean.setLoadOnStartup(1);
        registrationBean.addUrlMappings("/hystrix.stream");
        registrationBean.setName("HystrixMetricsStreamServlet");
        return registrationBean;
    }

    @Bean
    public FilterRegistrationBean corsFilterRegistration() {
        FilterRegistrationBean registration = new FilterRegistrationBean();
        registration.setDispatcherTypes(DispatcherType.REQUEST);
        registration.setFilter(new CORSFilter());
        registration.addUrlPatterns("/*");
        registration.setName("CorsFilter");
        registration.setOrder(Integer.MAX_VALUE);
        return registration;
    }

    //@Bean
    public ServletRegistrationBean servletRegistrationBean() {
        ServletRegistrationBean registration = new ServletRegistrationBean();
        registration.setServlet(new StatViewServlet());
        registration.setUrlMappings(Lists.newArrayList("/druid/*"));
        return registration;
    }

    @Bean(value = "threadPool")
    @Primary
    public ExecutorService buildThreadPool() {
        int cpuNum = Runtime.getRuntime().availableProcessors();
        logger.info("init buildThreadPool,cpuNum:{}....",cpuNum);
        ThreadFactory namedThreadFactory = new ThreadFactoryBuilder().setNameFormat("thread-pool-%d").build();
        int corePoolSize = cpuNum;
        int maxPoolSize = cpuNum * 2;
        long keepAliveTime = 10000L;
        BlockingQueue<Runnable> workQueue = new LinkedBlockingQueue<>();
        RejectedExecutionHandler rejectedExecutionHandler = new ThreadPoolExecutor.CallerRunsPolicy();
        return new ThreadPoolExecutor(corePoolSize, maxPoolSize, keepAliveTime,
                TimeUnit.MILLISECONDS, workQueue, namedThreadFactory, rejectedExecutionHandler);
    }

}
